package com.cskaoyan.javase.array._6call;

import java.util.Arrays;

/**
 * 什么是方法的传值/传参问题?
 *
 * 调用方法时，我们需要传递实参给方法，在方法内部有可能会改变这些实参的值。
 * 那么方法执行完毕后，这些实参的值在原先的方法中会怎么变呢？这就是方法的传值问题。
 *
 * Java中两种传值的方式:
 * 1.值传递(call by value)指的是方法得到的是实参变量的拷贝,而不是实参变量本身
 *      如果是值传递,方法是不能修改实参变量的取值的,因为方法修改的是拷贝
 *
 * 2.引用传递(call by reference)指的是方法得到的就是实参本身(直接访问实参变量的地址)
 *      如果是引用,方法是可以修改实参变量的取值,因为获取地址了,就可以直接去修改.
 *
 * 那么Java的传值方式究竟是什么样的呢?写代码测试一下
 * ----------------------------------------------------
 * 分两种情况:
 * 1.测试基本数据类型实参
 *      发现方法是不能修改实参变量的取值的,所以至少对于基本数据类型实参
 *      Java是值传递的.
 *
 * 2.测试引用数据类型实参
 *      发现方法是可以修改引用数据类型实参变量的取值的
 *      所以至少对于引用数据类型实参
 *      Java是引用传递的
 * ----------------------------------------------------
 * 以上圈起来的部分,是典型的关于Java传值方式的错误言论
 * 因为它测试的方式是有问题的,是不严谨的,没有深入考虑
 * 实际上:
 *      对于Java任何数据类型实参而言,Java都只有值传递,没有任何引用传递!
 *
 * 知道了Java方法是值传递的以后,可以得出以下结论:
 *      1.不能修改基本数据类型的实参的值，也不能修改引用数据类型实参"引用"的取值。
 *          因为一个方法不能修改其它方法中局部变量的取值。
 *          一旦违反上述原则，那么局部变量就不"局部"了。
 *
 *      2.方法可以改变对象的状态.
 *          方法传入一个引用数据类型实参,可以通过传入的引用,去修改对象中元素的取值,改变对象的状态
 *
 * @since 10:12
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        int num = 10;
        doubleIntValue(num);
        System.out.println(num);
        System.out.println("--------------");
        int[] arr = {1, 2, 3};
        System.out.println("调用方法之前的arr:" + Arrays.toString(arr));
        doubleIntArrElement(arr);
        System.out.println("调用方法之后的arr:" + Arrays.toString(arr));
        System.out.println("------------------");
        int[] arr1 = {6, 6, 6};
        int[] arr2 = {7, 7, 7};
        System.out.println("交换之前arr1:" + Arrays.toString(arr1));
        System.out.println("交换之前arr2:" + Arrays.toString(arr2));
        /*
            假如Java是值传递,方法中交换的就是引用的拷贝,对原先的引用没有影响,交换失败
            假如Java是引用传递,方法中交换的就是引用本身,交换成功
         */
        swapReference(arr1, arr2);
        System.out.println("交换之后arr1:" + Arrays.toString(arr1));
        System.out.println("交换之后arr2:" + Arrays.toString(arr2));
    }

    // 通过一个方法将int实参变为二倍
    public static void doubleIntValue(int num) {
        num *= 2;
    }

    // 通过一个方法将数组元素变为二倍
    public static void doubleIntArrElement(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] *= 2;
        }
    }

    // 通过一个方法交换两个int数组的引用,修改引用数据类型的引用
    public static void swapReference(int[] arr1, int[] arr2) {
        int[] temp = arr1;
        arr1 = arr2;
        arr2 = temp;
        System.out.println("交换方法中arr1:" + Arrays.toString(arr1));
        System.out.println("交换方法中arr2:" + Arrays.toString(arr2));
    }


}
